interface Func {
  (...args: any[]): void
}

/**
 * @description 从右到左执行 最后一个函数可以传多个参数，其余最多一个参数
 * @param {...Function} funcs
 * @returns {Function} 新函数
 * @example
 * ---------------------------
 * compose(f, g, h)
 * // => (...args) => f(g(h(...args)))
 */
export const compose = function (...funcs: Func[]): Func {
  if (funcs.length === 0) return (...arg) => arg
  if (funcs.length === 1) return funcs[0]
  return funcs.reduce((pre, cur) => (...args) => pre(cur(...args)))
}


/**
 * @description 从左到右执行  首个函数可以传多个参数，其余最多一个参数
 * @param {...Function} funcs
 * @returns {Function} 新函数
 * @example
 * ---------------------------
 * compose(f, g, h)
 * // => (...args) => h(g(f(...args)))
 */
export const pipe = function (...funcs: Func[]): Func {
  if (funcs.length === 0) return (...arg) => arg
  if (funcs.length === 1) return funcs[0]
  return funcs.reduce((pre, cur) => (...args) => cur(pre(...args)))
}
